/*
 * JaLingo, http://jalingo.sourceforge.net/
 *
 * Copyright (c) 2002-2006 Oleksandr Shyshko
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package ja.lingo.application.util.misc;

import ja.centre.util.assertions.Arguments;
import ja.centre.util.regex.Replacers;
import ja.centre.util.regex.IReplacer;

public class Strings {
    private static final int MAX_LENGTH = 64;
    private static final String MAX_LENGTH_SUFFIX = "...";

    private static IReplacer[] escapeHtmlReplacers = {
            Replacers.plain( "&", "&amp;", "&" ),
            Replacers.plain( "\"", "&quot;", "\"" ),
            Replacers.plain( "<", "&lt;", "<" ),
            Replacers.plain( ">", "&gt;", ">" )
    };
    private static IReplacer[] unescapeSqlReplacsers = {
            Replacers.plain( "\\'", "'", "\\'" ),
            Replacers.plain( "\\\"", "\"", "\\\"" ),
            Replacers.plain( "\\n", "\n", "\\n" )
    };


    // Taken from http://www.merriampark.com/ldjava.htm
    public static int getLevenshteinDistance( String s, String t ) {
        if ( s == null || t == null ) {
            throw Arguments.doThrow( "Strings must not be null" );
        }

        int n = s.length();// length of s
        int m = t.length();// length of t

        if ( n == 0 ) {
            return m;
        } else if ( m == 0 ) {
            return n;
        }

        int p[] = new int[n + 1];//'previous' cost array, horizontally
        int d[] = new int[n + 1];// cost array, horizontally
        int _d[];//placeholder to assist in swapping p and d

        // indexes into strings s and t
        int i;// iterates through s
        int j;// iterates through t

        char t_j;// jth character of t
        int cost;// cost

        for ( i = 0; i <= n; i++ ) {
            p[i] = i;
        }

        for ( j = 1; j <= m; j++ ) {
            t_j = t.charAt( j - 1 );
            d[0] = j;

            for ( i = 1; i <= n; i++ ) {
                cost = s.charAt( i - 1 ) == t_j ? 0 : 1;
                // minimum of cell to the left+1, to the top+1, diagonally left and up +cost
                d[i] = Math.min( Math.min( d[i - 1] + 1, p[i] + 1 ), p[i - 1] + cost );
            }

            // copy current distance counts to 'previous row' distance counts
            _d = p;
            p = d;
            d = _d;
        }

        // our last action in the above loop was to switch d and p, so p now
        // actually has the most recent cost counts
        return p[n];
    }

    public static String cutIfNecessary( String subject ) {
        return subject.length() > MAX_LENGTH
                ? subject.substring( 0, MAX_LENGTH ) + MAX_LENGTH_SUFFIX
                : subject;
    }

    public static boolean isEmpty( String text ) {
        return text == null || text.trim().length() == 0;
    }

    public static String escapeHtml( String text ) {
        return Replacers.replaceAll( text, escapeHtmlReplacers );
    }

    public static String unescapeSql( String text ) {
        return Replacers.replaceAll( text, unescapeSqlReplacsers );
    }
}
